package org.artifact.core.context.session;

import java.net.SocketAddress;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.artifact.core.context.packet.IPacket;
import org.artifact.core.enums.SessionStatusEnum;

public abstract class ISession {
	
	private Map<ISessionAttr, Object> attr = new ConcurrentHashMap<>();
	
	private volatile SessionStatusEnum status;
	
	/***
	 * 取得SessionId
	 * 
	 * @return
	 */
	public abstract String getId();

	/**
	 * 获得本地IP
	 * 
	 * @return
	 */
	public abstract SocketAddress localAddress();

	/**
	 * 获得远程IP
	 * 
	 * @return
	 */
	public abstract SocketAddress remoteAddress();
	
	/**
	 * 取得TCP通道
	 * @return
	 */
	public abstract <T> T getChannel();

	/**
	 * 设置TCP通道
	 * @param channel
	 */
	public abstract void setChannel(Object channel);

	/**
	 * 关闭
	 */
	public abstract void close();
	
	/**
	 * Returns {@code true} if the tcp/ip socket channel is open an may get
	 * active later
	 */
	public abstract boolean isOpen();

	/**
	 * 是否活跃
	 * @return
	 */
	public abstract boolean isActive();
	
	/**
	 * 是否能写数据
	 * @return
	 */
	public abstract boolean isWritable();
	
	/**
	 * 写数据
	 */
	protected abstract void writeAndFlush(IPacket packet);

	/**
	 * 发送消息
	 * @param packet
	 */
	public void sendPacket(IPacket packet){
		if (isActive() && isWritable()) {
			writeAndFlush(packet);
		}
	}
	
	/**
	 * 接收消息
	 * @param packet
	 */
	public abstract void receivePacket(IPacket packet);
	
	/**
	 * 取得属性
	 * 
	 * @param key
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public <T> T getAttr(ISessionAttr key){
		return (T) attr.get(key);
	}

	/**
	 * 设置属性
	 * 
	 * @param key
	 * @param value
	 */
	public void setAttr(ISessionAttr key, Object value){
		attr.put(key, value);
	}

	/**
	 * 删除属性
	 * 
	 * @param key
	 */
	public void removeAttr(ISessionAttr key){
		attr.remove(key);
	}
	
	/**
	 * 清空属性
	 */
	public void clearAttr(){
		attr.clear();
	}

	public SessionStatusEnum getStatus() {
		return status;
	}

	public void setStatus(SessionStatusEnum status) {
		this.status = status;
	}
}
